<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>贪吃蛇</title>
    <style>
        *{
            padding: 0;
            margin: 0;
        }
        #map{
            width: 400px;
            height: 400px;
            background-color: black;
            position: relative;
        }
    </style>
</head>
<body>
<div id="map"></div>
<script>
    // 地图类
    class Map{
        constructor(el, rect = 10) {
            this.el = el
            this.rect = rect
            this.data = []
            this.rows = Math.ceil(Map.getStyle(el,'height') / rect)
            this.cells = Math.ceil(Map.getStyle(el,'width') / rect)
            Map.setStyle(el,'height',this.rows*rect)
            Map.setStyle(el,'width',this.cells*rect)
        }
        static getStyle(el,attr){
            return parseFloat(getComputedStyle(el)[attr])
        }
        static setStyle(el,attr,val){
            return el.style[attr] = val + 'px'
        }

        // 通过setData，往面板里面添加数据
        setData(newData){
            this.data = this.data.concat(newData)
        }
        clearData(){
            this.data.length = 0
        }
        include({x,y}){
            return !!this.data.find(item=> item.x === x && item.y === y)
        }
        render(){
            console.log(this.data)
            this.el.innerHTML = this.data.map(item=>{
                return `<span style="position: absolute;left: ${item.x*this.rect}px;top: ${item.y*this.rect}px;
                            width: ${this.rect}px;height: ${this.rect}px;background-color: ${item.color}"></span>`
            }).join("")
        }
    }
    // 食物类
    class Food{
        constructor(map, colors = ["red","pink","yellow","blue"]) {
            this.map = map
            this.colors = colors
            this.data = null
            this.create()
        }
        create(){
            let x = Math.floor(Math.random()*this.map.cells)
            let y = Math.floor(Math.random()*this.map.rows)
            let color = this.colors[Math.ceil(Math.random()*this.colors.length-1)]
            this.data = {x,y,color}
            console.log(this.data)
            // 如果重合，就重新生成一个点
            if(this.map.include(this.data)){
                this.create()
            }
            this.map.setData(this.data)
        }
    }

    // snake类
    class Snake{
        constructor(map,food) {
            this.data = [
                {
                    x:6,
                    y:4,
                    color:'green'
                },
                {
                    x:5,
                    y:4,
                    color:'#fff'
                },
                {
                    x:4,
                    y:4,
                    color:'#fff'
                },
                {
                    x:3,
                    y:4,
                    color:'#fff'
                },
                {
                    x:2,
                    y:4,
                    color:'#fff'
                }
            ]
            this.map = map
            this.food = food
            this.map.setData(this.data)
            this.direction = 'right'
        }
        move(){
            let i = this.data.length-1
            this.lastData = {
                x:this.data[i].x,
                y:this.data[i].y,
                color:this.data[i].color
            }
            // 修改为上一个格子的位置
            for (i;i>0;i--){
                this.data[i].x = this.data[i-1].x
                this.data[i].y = this.data[i-1].y
            }
            switch (this.direction){
                case "left":
                    this.data[0].x--
                    break
                case "right":
                    this.data[0].x++
                    break
                case "top":
                    this.data[0].y--
                    break
                case "bottom":
                    this.data[0].y++
            }
        }
        changeDir(dir){
            // 如果蛇此时正在上下移动，那我们就只能修改蛇让它左右移动
            if(this.direction === 'right' || this.direction === 'left'){
                if(dir === 'right'|| dir === 'left'){
                    return false // 修改方向失败
                }
            }else {
                // 如果蛇此时正在左右移动，那我们就只能修改蛇让它上下移动
                if(dir === 'top'|| dir === 'bottom'){
                    return false // 修改方向失败
                }
            }
            this.direction = dir
            return true

        };
        eatFood(){
            this.data.push(this.lastData)
            this.map.setData(this.lastData)
        }
    }

    {
        let map = document.getElementById('map')
        let gameMap = new Map(map,10)
        let gameFood = new Food(gameMap)
        let gameSnake = new Snake(gameMap,gameFood)
        setInterval(()=>{
            gameSnake.move()
            gameMap.render()
        },200)
        setTimeout(()=>{
            gameSnake.changeDir('bottom')
            gameSnake.eatFood()
        },2000)
        setTimeout(()=>{
            gameSnake.changeDir('right')
            gameSnake.eatFood()
        },4000)
    }
</script>
</body>
</html>
